package org.hackystat.ui.projectviewer.gwt.testsuite;

import static org.hackystat.telemetry.service.server.ServerProperties.DAILYPROJECTDATA_FULLHOST_KEY;
import static org.hackystat.telemetry.service.server.ServerProperties.SENSORBASE_FULLHOST_KEY;

import java.io.File;
import java.net.ServerSocket;
import java.net.Socket;

import javax.xml.datatype.XMLGregorianCalendar;

import org.hackystat.sensorbase.client.SensorBaseClient;
import org.hackystat.sensorbase.resource.projects.jaxb.Project;
import org.hackystat.sensorbase.resource.projects.jaxb.Properties;
import org.hackystat.sensorbase.resource.projects.jaxb.Property;
import org.hackystat.sensorbase.resource.projects.jaxb.UriPatterns;
import org.hackystat.utilities.tstamp.Tstamp;

public class GWTTestHelperServer {

  /** The Sensorbase server used in these tests. */
  @SuppressWarnings("unused")
  private static org.hackystat.sensorbase.server.Server sensorbaseServer;
  /** The DailyProjectData server used in these tests. */
  @SuppressWarnings("unused")
  private static org.hackystat.dailyprojectdata.server.Server dpdServer;
  /** The Telemetry server used in these tests. */
  @SuppressWarnings("unused")
  private static org.hackystat.telemetry.service.server.Server tServer;

  // basic settings
  private static final String admin = "admin@hackystat.org";
  private static final String testUser1 = "ProjectViewerRPCTestUser1@hackystat.org";
  private static final String testUser2 = "ProjectViewerRPCTestUser2@hackystat.org";
  @SuppressWarnings("unused")
  private static final String testUser3 = "ProjectViewerRPCTestUser3@hackystat.org";
  @SuppressWarnings("unused")
  private static final String defaultProjectName = "Default";

  // couple of projects for test purposes
  private static final String testProject1Name = "Test1";
  private static final UriPatterns testProject1Uris = new UriPatterns();
  private static final String testProject1Uri1 = "**/bar/**";
  private static final String testProject1Uri2 = "**/test1/uri2/**";
  private static final Properties testProject1Properties = new Properties();
  private static final Property testProject1Property1 = new Property();
  private static final Property testProject1Property2 = new Property();
  private static final String testProject1Prop1 = "prop1";
  private static final String testProject1Val1 = "prop1_value";
  private static final String testProject1Prop2 = "prop2";
  private static final String testProject1Val2 = "prop2_value";
  private static final String testProject1Desc = "TestProject #1";
  private static final XMLGregorianCalendar testProject1Start = Tstamp.incrementDays(Tstamp
      .makeTimestamp(System.currentTimeMillis()), -360);
  private static final XMLGregorianCalendar testProject1End = Tstamp.incrementDays(Tstamp
      .makeTimestamp(System.currentTimeMillis()), 360);

  private static final String testProject2Name = "Test2";
  private static final UriPatterns testProject2Uris = new UriPatterns();
  private static final String testProject2Uri1 = "**/test2/uri1/**";
  private static final String testProject2Uri2 = "**/test2/uri2/**";
  private static final String testProject2Desc = "TestProject #2";
  private static final XMLGregorianCalendar testProject2Start = Tstamp.incrementDays(Tstamp
      .makeTimestamp(System.currentTimeMillis()), -360);
  private static final XMLGregorianCalendar testProject2End = Tstamp.incrementDays(Tstamp
      .makeTimestamp(System.currentTimeMillis()), 360);

  private static final String testProject3Name = "Test3";
  private static final UriPatterns testProject3Uris = new UriPatterns();
  private static final String testProject3Uri1 = "**/test3/uri1/**";
  private static final String testProject3Uri2 = "**/test3/uri2/**";
  private static final String testProject3Desc = "TestProject #3";
  private static final XMLGregorianCalendar testProject3Start = Tstamp.incrementDays(Tstamp
      .makeTimestamp(System.currentTimeMillis()), -360);
  private static final XMLGregorianCalendar testProject3End = Tstamp.incrementDays(Tstamp
      .makeTimestamp(System.currentTimeMillis()), 360);

  private static SensorBaseClient adminClient;
  private static SensorBaseClient sensorBaseClient1;
  private static SensorBaseClient sensorBaseClient2;

  /**
   * @param args The command-line args.
   * @throws Exception If error encountered.
   */
  public static void main(String[] args) throws Exception {

    // Create testing versions of the Sensorbase, DPD, and Telemetry servers.
    sensorbaseServer = org.hackystat.sensorbase.server.Server.newTestInstance();
    dpdServer = org.hackystat.dailyprojectdata.server.Server.newTestInstance();
    tServer = org.hackystat.telemetry.service.server.Server.newTestInstance();

    // making projects attributes
    //
    testProject1Uris.getUriPattern().add(testProject1Uri1);
    testProject1Uris.getUriPattern().add(testProject1Uri2);
    testProject1Property1.setKey(testProject1Prop1);
    testProject1Property1.setValue(testProject1Val1);
    testProject1Property2.setKey(testProject1Prop2);
    testProject1Property2.setValue(testProject1Val2);
    testProject1Properties.getProperty().add(testProject1Property1);
    testProject1Properties.getProperty().add(testProject1Property2);
    testProject2Uris.getUriPattern().add(testProject2Uri1);
    testProject2Uris.getUriPattern().add(testProject2Uri2);
    testProject3Uris.getUriPattern().add(testProject3Uri1);
    testProject3Uris.getUriPattern().add(testProject3Uri2);
    // Connect to the sensorbase
    adminClient = new SensorBaseClient(getSensorBaseHostName(), admin, admin);
    adminClient.authenticate();
    // register users
    SensorBaseClient.registerUser(getSensorBaseHostName(), testUser1);
    SensorBaseClient.registerUser(getSensorBaseHostName(), testUser2);

    // create clients
    sensorBaseClient1 = new SensorBaseClient(getSensorBaseHostName(), testUser1, testUser1);
    sensorBaseClient1.authenticate();
    sensorBaseClient2 = new SensorBaseClient(getSensorBaseHostName(), testUser2, testUser2);
    sensorBaseClient2.authenticate();

    // cleanup accidental artefacts
    adminClient.deleteProject(admin, testProject1Name);
    adminClient.deleteProject(admin, testProject2Name);
    adminClient.deleteProject(admin, testProject3Name);

    sensorBaseClient1.deleteProject(testUser1, testProject1Name);
    sensorBaseClient1.deleteProject(testUser1, testProject2Name);
    sensorBaseClient1.deleteProject(testUser1, testProject3Name);

    sensorBaseClient2.deleteProject(testUser2, testProject1Name);
    sensorBaseClient2.deleteProject(testUser2, testProject2Name);
    sensorBaseClient2.deleteProject(testUser2, testProject3Name);
    // add new projects
    //
    // owner - user #1
    sensorBaseClient1.putProject(makeProject1());
    sensorBaseClient1.putProject(makeProject3());
    //
    // owner - user #2
    sensorBaseClient2.putProject(makeProject2());

    // make a socket to listen for shutdown signal.
    //
    ServerSocket server = new ServerSocket(9000);
    // wait until request got
    System.out.println("Waiting for shutdown signal at socket #9000");

    String flagFileName = System.getProperty("user.dir") + "/ready.tmp";
    File f = new File(flagFileName);
    f.createNewFile();

    @SuppressWarnings("unused")
    Socket sock = server.accept();

    System.exit(0);
  }

  /**
   * Create a test project1.
   *
   * @return The test project 1.
   */
  private static Project makeProject1() {
    Project project = new Project();
    project.setOwner(testUser1);
    project.setName(testProject1Name);
    project.setDescription(testProject1Desc);
    project.setStartTime(testProject1Start);
    project.setEndTime(testProject1End);
    project.setUriPatterns(testProject1Uris);
    project.setProperties(testProject1Properties);
    return project;
  }

  /**
   * Create a test project2.
   *
   * @return The test project 2.
   */
  private static Project makeProject2() {
    Project project = new Project();
    project.setOwner(testUser2);
    project.setName(testProject2Name);
    project.setDescription(testProject2Desc);
    project.setStartTime(testProject2Start);
    project.setEndTime(testProject2End);
    project.setUriPatterns(testProject2Uris);
    return project;
  }

  /**
   * Create a test project3.
   *
   * @return The test project 3.
   */
  private static Project makeProject3() {
    Project project = new Project();
    project.setOwner(testUser1);
    project.setName(testProject3Name);
    project.setDescription(testProject3Desc);
    project.setStartTime(testProject3Start);
    project.setEndTime(testProject3End);
    project.setUriPatterns(testProject3Uris);
    return project;
  }

  /**
   * Returns the hostname associated with this Telemetry test server.
   *
   * @return The host name, including the context root.
   */
  protected String getTelemetryHostName() {
    return tServer.getServerProperties().getFullHost();
  }

  /**
   * Returns the sensorbase hostname that this Telemetry server communicates with.
   *
   * @return The host name, including the context root.
   */
  protected static String getSensorBaseHostName() {
    return tServer.getServerProperties().get(SENSORBASE_FULLHOST_KEY);
  }

  /**
   * Returns the sensorbase hostname that this Telemetry server communicates with.
   *
   * @return The host name, including the context root.
   */
  protected String getDailyProjectDataHostName() {
    return tServer.getServerProperties().get(DAILYPROJECTDATA_FULLHOST_KEY);
  }
}
